package com.zz.common.utils.common;


import cn.hutool.core.codec.Base64;
import com.zz.common.base.dto.ResponseDTO;
import com.zz.common.constants.ApiConstants;
import com.zz.common.constants.JwtConstant;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * @author zl
 * @version 1.0
 */
@Component
public class TokenUtils {

    /**
     * @Author: zl
     * @Description: jwt生成token
     * @Params: name一般是登录账户名  id是账户id或者随机数值
     * @Return
     */
    public static String geneJsonWebToken(String name, String id) {
        return geneJsonWebToken(name, id, JwtConstant.JWT_TTL);
    }

    /**
     * jwt生成token
     *
     * @param name      登陆者账户名
     * @param id        登陆者id
     * @param ttlMillis 过期时间
     * @return token
     */
    public static String geneJsonWebToken(String name, String id, long ttlMillis) {
        // 系统时间
        long nowMillis = System.currentTimeMillis();
        JwtBuilder jwtBuilder = Jwts.builder()
                .subject(JwtConstant.JWT_SUBJECT)
                .claim("userId", id)
                .claim("userName", name)
                .issuedAt(new Date(nowMillis))
                .signWith(generateHmacKey(), Jwts.SIG.HS256);
        if (ttlMillis >= 0) {
            // 设置过期时间
            jwtBuilder.expiration(new Date(nowMillis + ttlMillis));
        }
        return jwtBuilder.compact();
    }

    /**
     * @Author: zl
     * @Description: 校验token
     * @Params:
     * @Return
     */
    public static ResponseDTO<Claims> checkJWT(String token) {
        ResponseDTO<Claims> res = new ResponseDTO<>();
        Claims claims;
        try {
            claims = parseJWT(token);
            res.setCode(ApiConstants.RESULT_SUCCESS);
            res.setMessage(ApiConstants.MESSAGE_SUCCESS);
            res.setData(claims);
        } catch (ExpiredJwtException e) {
            res.setMessage(JwtConstant.JWT_ERR_MSG_EXPIRE);
            res.setCode(JwtConstant.JWT_ERR_CODE_EXPIRE);
        } catch (JwtException e) {
            res.setMessage(JwtConstant.JWT_ERR_MSG_FAIL);
            res.setCode(JwtConstant.JWT_ERR_CODE_FAIL);
        }
        return res;
    }

    /**
     * 解析JWT字符串
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) {
        SecretKey secretKey = generateHmacKey();
        return Jwts.parser()
                .verifyWith(secretKey)
                .build()
                .parseSignedClaims(jwt)
                .getPayload();
    }

    /**
     * 生成 HMAC 密钥-HmacSHA256
     *
     * @return
     */
    public static SecretKey generateHmacKey() {
        try {
            byte[] secret = Base64.decode(JwtConstant.JWT_SECRET);
            return new SecretKeySpec(secret, "HmacSHA256");
        } catch (Exception e) {
            throw new RuntimeException("Invalid HMAC key", e);
        }
    }

    public static String generateValidSecretKey() {
        KeyGenerator keyGen = null;
        try {
            keyGen = KeyGenerator.getInstance("HmacSHA256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        keyGen.init(256); // 明确指定256位
        SecretKey secretKey = keyGen.generateKey();
        return Base64.encode(secretKey.getEncoded());
    }

//    public static void main(String[] args) {
//
//        String token = geneJsonWebToken("zhang.lei", "123");
//        System.out.println(token);
//        ResponseDTO<Claims> claimsResponseDTO = checkJWT(token);
//
//        System.out.println(claimsResponseDTO.getCode());
//        System.out.println(claimsResponseDTO.getData().get("userId"));
//        System.out.println(claimsResponseDTO.getData().get("userName"));
//        System.out.println(claimsResponseDTO.getData().getSubject());
//        try {
//            Thread.sleep(4000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        System.out.println(checkJWT(token).getCode());
//    }

}

